#include"CentralCache.h"
#include"PageCache.h"
#include"Common.h"
CentralCache CentralCache::_instance;

size_t CentralCache::FetchRangeObj(void*& start, void*& end, size_t batchNum, size_t size)
{
	size_t index = SizeClass::Index(size);
	_spanlists[index]._mutex.lock();
	Span* span = GetOneSpan(_spanlists[index], size);
	assert(span);
	assert(span->_free_list);
	int i = 0;
	start = span->_free_list;
	end = start;
	size_t actualnum = 1;
	while (i < batchNum - 1 && GetNextObj(end) != nullptr)
	{
		end = GetNextObj(end);
		i++;
		actualnum++;
	}
	span->_free_list = GetNextObj(end);
	GetNextObj(end) = nullptr;
	span->_use_count += actualnum;
	_spanlists->_mutex.unlock();
	return actualnum;
}
Span* CentralCache::GetOneSpan(SpanList& list, size_t size)
{
	Span* span = list.Begin();
	while (span != list.End())
	{
		if (span->_free_list != nullptr)
		{
			return span;
		}
		else
		{
			span = span->next;
		}
	}
	list._mutex.unlock();
	PageCache::Instance()->_mtx.lock();
	Span* s = PageCache::Instance()->NewSpan(SizeClass::NumMovePage(size));
	s->_is_used = true;
	s->_object_size = size;
	PageCache::Instance()->_mtx.unlock();
	char* start = (char*)((s->page_id) << PAGE_SHIFT);
	size_t bytes = s->n << PAGE_SHIFT;
	char* end = start + bytes;
	s->_free_list = start;
	void* tail = start;
	start += size;
	while (start + size < end)
	{
		GetNextObj(tail) = start;
		tail = start;
		start += size;
	}
	GetNextObj(tail) = nullptr;
	list._mutex.lock();
	list.PushFront(s);
	return s;
}